package com.xxy.book.service;

import com.xxy.book.cache.Cache;
import com.xxy.book.constant.CacheName;
import com.xxy.book.dao.UserMapper;
import com.xxy.book.dto.UserDetailDTO;
import com.xxy.book.entity.User;
import com.xxy.book.enums.StatusCodeEnum;
import com.xxy.book.form.LoginForm;
import com.xxy.book.form.RegisterForm;
import com.xxy.book.provider.JwtProvider;
import com.xxy.book.util.BookUtil;
import com.xxy.book.util.MailClient;
import com.xxy.book.vo.AccessToken;
import com.xxy.book.vo.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

/**
 * @Author Xu XianYun
 * @Date 2022-12-27
 * @Description
 */
@Service
public class UserService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private Cache caffeineCache;

    @Autowired
    private JwtProvider jwtProvider;

    @Resource
    private UserMapper userMapper;

    @Resource
    private MailClient mailClient;

    @Value("${bookManager.path.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    /**
     * @Description 用户注册
     * @Author Xu XiangYun
     * @Date 2022-12-27 19:01
     * @param registerForm
     * @return ResultVO
     */
    public Result register(RegisterForm registerForm) {
        if (registerForm == null) {
            throw new IllegalArgumentException("参数不能为空");
        }

        if (StringUtils.isBlank(registerForm.getUsername())) {
            return Result.fail("用户名不能为空");
        }

        if (StringUtils.isBlank(registerForm.getPassword())) {
            return Result.fail("密码不能为空");
        }

        if (StringUtils.isBlank(registerForm.getEmail())) {
            return Result.fail("邮箱不能为空");
        }

        // 验证用户名是否存在
        User user = userMapper.selectUserByName(registerForm.getUsername());
        if (user != null) {
            return Result.fail("用户名已存在, 请更改用户名");
        }

        //验证邮箱是否存在
        user = userMapper.selectUserByEmail(registerForm.getEmail());
        if (user != null) {
            return Result.fail("该邮箱已被使用，请更改邮箱");
        }

        //用户注册
        user = new User();
        user.setUsername(registerForm.getUsername());
        user.setEmail(registerForm.getEmail());
        user.setSalt(BookUtil.generateUUID().substring(0, 5));
        user.setPassword(BookUtil.md5(registerForm.getPassword() + user.getSalt()));
        user.setActivationCode(BookUtil.generateUUID());

        //设置为未激活状态
        user.setStatus(0);
        user.setCreateTime(new Date());

        //插入数据库
        userMapper.insertUser(user);

        // http://localhost:8080/activation/用户id/激活码
        String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode();
        String content = "<!doctype html>\n" +
                "<html lang=\"en\">\n" +
                "<head>\n" +
                "    <meta charset=\"utf-8\">\n" +
                "\t<title>BookManager - 激活账号</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "\t<div>\n" +
                "\t\t<p>\n" +
                "\t\t\t" + user.getEmail() + ", 您好! \uD83D\uDE03\n" +
                "\t\t</p>\n" +
                "\t\t<p>\n" +
                "\t\t\t您正在注册 BookManager 图书管理系统, 这是一封激活邮件, 请点击\n" +
                "\t\t\t<a href=\""+ url +"\">此链接</a>,\n" +
                "\t\t\t激活您的 BookManager 账号! \uD83C\uDF89\n" +
                "\t\t</p>\n" +
                "\t</div>\n" +
                "</body>\n" +
                "</html>";

        mailClient.sendMail(user.getEmail(), "激活 Book-Manager 账号", content);

        return Result.ok(null, "用户已注册，待激活");
    }

    public Result login(LoginForm loginForm) {
        // 1.从数据查询用户信息
        User user = userMapper.selectUserByName(loginForm.getUsername());
        if (Objects.isNull(user)) {
            return Result.fail(StatusCodeEnum.USERNAME_NOT_EXIST);
        }

        //将前端密码加盐加密，用于 Spring Security 帮助我们认证
        String passwordAddSalt = BookUtil.md5(loginForm.getPassword() + user.getSalt());
        loginForm.setPassword(passwordAddSalt);

        // Spring Security 认证
        //1. 构建 UsernamePasswordAuthenticationToken 对象
        UsernamePasswordAuthenticationToken authenticationToken = new
                UsernamePasswordAuthenticationToken(loginForm.getUsername(), loginForm.getPassword());
        //2. 认证
        Authentication authentication = authenticationManager.authenticate(authenticationToken);
        //3. 保存认证信息
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //4. 生成自定义 token
        UserDetailDTO userDetailDTO = (UserDetailDTO) authentication.getPrincipal();
        AccessToken accessToken = jwtProvider.createToken((UserDetails) userDetailDTO);
        // 5 放入缓存
        caffeineCache.put(CacheName.USER, userDetailDTO.getUsername(), userDetailDTO);
        return Result.ok(accessToken);
    }

    /**
     * @Description
     * @Author Xu XiangYun
     * @Date 2023-01-05 20:07
     * @param userId
     * @param code
     * @return Result
     */
    public Result activation(Integer userId, String code) {
        //查询用户激活状态
        User user = userMapper.selectUserById(userId);
        if (user.getStatus() == 1) {
            return Result.ok(null, "用户已经激活，请勿重复激活");
        }
        else if (user.getActivationCode().equals(code)) {
            return Result.ok(null, "用户激活成功");
        } else {
            return Result.fail("用户激活失败");
        }
    }
}
